package com.mobile.mobilehardware.emulator;

import com.mobile.mobilehardware.utils.Logs;
import ohos.app.Context;
import ohos.bundle.BundleInfo;
import ohos.rpc.RemoteException;
import ohos.utils.zson.ZSONObject;

import java.io.*;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Scanner;


/**
 * @author guxiaonian
 */
class EmulatorInfo {
    /**
     * log TAG
     */
    private static final String TAG = EmulatorInfo.class.getSimpleName();

    static ZSONObject checkEmulator(Context context) {
        EmulatorBean emulatorBean = new EmulatorBean();
        try {
            boolean checkBuild = isEmulatorAbsoluly();
            boolean checkPipes = checkPipes();
            boolean checkQEmuDriverFile = checkQEmuDriverFile("/proc/tty/drivers") || checkQEmuDriverFile("/proc/cpuinfo");
            boolean checkCpuInfo = readCpuInfo();
            emulatorBean.setCheckBuild(checkBuild);
            emulatorBean.setCheckPipes(checkPipes);
            emulatorBean.setCheckQEmuDriverFile(checkQEmuDriverFile);
            emulatorBean.setCheckCpuInfo(checkCpuInfo);
        } catch (Exception e) {
            Logs.i(TAG, e.toString());
        }
        return emulatorBean.toJSONObject();

    }

    /**
     * 通过cpu的信息是否包含amd和intel来判断
     *
     * @return true为模拟器
     */
    private static boolean readCpuInfo() {
        String result = "unknown";
        try {
            String[] args = {"/system/bin/cat", "/proc/cpuinfo"};
            ProcessBuilder cmd = new ProcessBuilder(args);

            Process process = cmd.start();
            StringBuilder sb = new StringBuilder();
            String readLine;
            BufferedReader responseReader = new BufferedReader(new InputStreamReader(process.getInputStream(), "utf-8"));
            while ((readLine = responseReader.readLine()) != null) {
                sb.append(readLine);
            }
            responseReader.close();
            result = sb.toString().toLowerCase(Locale.getDefault());
        } catch (Exception ex) {
            Logs.i(TAG, ex.toString());
        }
        return (result.contains("intel") || result.contains("amd"));
    }


    /**
     * qemu特有的驱动列表
     */
    private static final String[] KNOWN_QEMU_DRIVERS = {
            "goldfish"
    };

    /**
     * 驱动程序的列表
     * @param name drive name
     * @return true为模拟器
     */
    private static boolean checkQEmuDriverFile(String name) {
        File driverFile = new File(name);
        if (driverFile.exists() && driverFile.canRead()) {
            byte[] data = new byte[1024];
            try {
                InputStream inStream = new FileInputStream(driverFile);
                inStream.read(data);
                inStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            String driverData = new String(data);
            for (String knownQemuDriver : KNOWN_QEMU_DRIVERS) {
                if (driverData.contains(knownQemuDriver)) {
                    return true;
                }
            }
        }
        return false;
    }

    /**
     * 设备通道文件，只兼容了qemu模拟器
     */
    private static final String[] KNOWN_PIPES = {
            "/dev/socket/qemud",
            "/dev/qemu_pipe"
    };


    /**
     * 检测“/dev/socket/qemud”，“/dev/qemu_pipe”这两个通道设备文件特征
     *
     * @return true为模拟器
     */
    private static boolean checkPipes() {
        for (String pipes : KNOWN_PIPES) {
            File qemuSocket = new File(pipes);
            if (qemuSocket.exists()) {
                return true;
            }
        }
        return false;
    }

    /**
     * 根据build静态资源来进行判断
     *
     * @return true为模拟器
     */
    private static boolean isEmulatorAbsoluly() {
        String[] properties = propertiesReader();
        String product = getPropValue(properties, "ro.product.name");
        String manufacturer = getPropValue(properties, "ro.product.manufacturer");
        String brand = getPropValue(properties, "ro.product.brand");
        String device = getPropValue(properties, "ro.product.device");
        String model = getPropValue(properties, "ro.product.model");
        String hardware = getPropValue(properties, "ro.hardware");
        String fingerprint = getPropValue(properties, "ro.build.fingerprint");
        if (product.contains("sdk") ||
                product.contains("sdk_x86") ||
                product.contains("sdk_google") ||
                product.contains("Andy") ||
                product.contains("Droid4X") ||
                product.contains("nox") ||
                product.contains("vbox86p") ||
                product.contains("aries")) {
            return true;
        } else if (manufacturer.contains("Genymotion") ||
                manufacturer.contains("Andy") ||
                manufacturer.contains("nox") ||
                manufacturer.contains("TiantianVM")) {
            return true;
        } else if (brand.contains("Andy")) {
            return true;
        } else if (device.contains("Andy") ||
                device.contains("Droid4X") ||
                device.contains("nox") ||
                device.contains("vbox86p") ||
                device.contains("aries")) {
            return true;
        } else if (model.contains("Emulator") ||
                model.contains("google_sdk") ||
                model.contains("Droid4X") ||
                model.contains("TiantianVM") ||
                model.contains("Andy")) {
            return true;
        } else if (hardware.contains("vbox86") ||
                hardware.contains("nox") ||
                hardware.contains("ttVM_x86")) {
            return true;
        } else if (fingerprint.contains("generic/sdk/generic") ||
                fingerprint.contains("generic_x86/sdk_x86/generic_x86") ||
                fingerprint.contains("Andy") ||
                fingerprint.contains("ttVM_Hdragon") ||
                fingerprint.contains("generic/google_sdk/generic") ||
                fingerprint.contains("vbox86p") ||
                fingerprint.contains("generic/vbox86p/vbox86p")) {
            return true;
        } else {
            return false;
        }

    }

    /**
     * Used for existingDangerousProperties().
     *
     * @return - list of system properties
     */
    private static String[] propertiesReader() {
        InputStream inputstream = null;
        try {
            inputstream = Runtime.getRuntime().exec("getprop").getInputStream();
        } catch (IOException e) {
            Logs.i(TAG, e.toString());
        }
        if (inputstream == null) {
            return null;
        }

        String allProperties = "";
        try {
            allProperties = new Scanner(inputstream).useDelimiter("\\A").next();
        } catch (NoSuchElementException e) {
            Logs.i(TAG, e.toString());
        }
        return allProperties.split("\n");
    }

    private static String getPropValue(String[] props, String key) {
        String keystr = "[" + key + "]";
        for (String line : props) {
            if (line.contains(keystr)) {
                String val = line.split("]: ")[1];
                return val.substring(1, val.length() - 1);
            }
        }
        return "UNKNOWN";
    }

}
